from typing import Any, Dict, List, Optional, Union
from pydantic import BaseModel, Field


class Item(BaseModel):
    """
    表示从页面中提取出的一个结构化数据项。
    用户应继承此类来定义自己的数据模型。
    """
    pass


class Target(BaseModel):
    """
    定义一个爬取目标。
    """
    url: str = Field(..., description="要爬取的 URL")
    method: str = Field("GET", description="HTTP 请求方法")
    headers: Optional[Dict[str, str]] = Field(None, description="自定义请求头")
    cookies: Optional[Dict[str, str]] = Field(None, description="自定义 Cookies")
    data: Optional[Dict[str, Any]] = Field(None, description="POST 请求的表单数据")
    json_data: Optional[Any] = Field(None, alias="json", description="POST 请求的 JSON 数据")
    
    # 爬虫元数据
    downloader: Optional[str] = Field(None, description="指定用于此目标的下载器名称")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="可用于在不同阶段传递自定义数据的元数据字典")
    extractor: Optional[Any] = Field(None, description="指定用于此目标的提取器实例")


class Response(BaseModel):
    """
    封装了下载器返回的 HTTP 响应。
    """
    url: str = Field(..., description="响应的最终 URL (可能经过重定向)")
    status_code: int = Field(..., description="HTTP 状态码")
    headers: Dict[str, str] = Field(..., description="响应头")
    content: bytes = Field(..., description="原始响应体 (二进制内容)")
    text: str = Field(..., description="解码后的响应体 (文本内容)")
    
    # 关联的爬取目标
    target: Target = Field(..., description="发出此请求的原始 Target 对象")

    class Config:
        arbitrary_types_allowed = True 